//
//  GameScene.cpp
//  petgame
//
//  Created by zz on 2018/12/10.
//

#include "GameScene.hpp"

Scene* GameScene::createScene(int type){
//    创建游戏场景
    auto scene=Scene::create();
    auto layer=GameScene::create(type);
    scene->addChild(layer);
    return scene;
}

GameScene *GameScene::create(int type){
    
//    创建游戏对象
    auto game=new GameScene();
    
    if(game&&game->init(type)){
//        自动释放
        game->autorelease();
        return game;
    }else{
//        安全删除
        CC_SAFE_DELETE(game);
        return NULL;
    }
}
bool GameScene::init(int type){
    
//    初始化
    if(!Layer::init()){
    
        return false;
    }
//    初始化游戏数据
    this->selectindex=-1;//当前选择的游戏物体
    this->_isNothing=true;//f触摸位置是否持有游戏物体
    this->_isShowUnhappy=false;//是否在播放不高兴的动画
    this->_isShowHung=false;//是否在播放饥饿动画
    this->_isShowTire=false;//是否播放b疲劳动画
    this->_foodCount=0;//食物数量
    this->_type=type;
    this->_isToEat=true;//是否在吃东西
    this->_isToPlay=true;//是否在玩耍
    this->_isSelectPlay=false;//是否在选择了玩耍
    this->_selectIndexPlay=-1;//记录选择的游戏玩耍的物体
    this->_isToSleep=true;//是否在睡觉
    
    
//    获取屏幕尺寸
    this->visibleSize=Director::getInstance()->getVisibleSize();
    this->origin=Director::getInstance()->getVisibleOrigin();
//    获取商品管理类对象
    auto manager=ShopManager::getInstance();
    this->addChild(manager);
//    设置背景
    auto background=Sprite::create("bg2.jpg");
    background->setPosition(this->visibleSize/2);
    background->setScale(1.2);
    this->addChild(background);
//    初始化ui
    this->initUI();
//    创建精神值progessbar
    this->k1=Spirit::create(SPIRIT,12,Vec2(25,this->visibleSize.height-30));
    this->addChild(this->k1);
    //    创建饥饿值progessbar

    this->k2=Spirit::create(HAPPY,12,Vec2(140,this->visibleSize.height-30));
    this->addChild(this->k2);
    
       //    创建开心值progessbar
    this->k3=Spirit::create(HUNGER,12,Vec2(260,this->visibleSize.height-30));
    this->addChild(this->k3);
    
//    创建游戏主角
    this->player=Player::create(PETTYPE::DOG,PETSTATUS::SLEEP,Vec2(this->visibleSize.width/2,this->visibleSize.height/2-140));
    this->addChild(player);
//    游戏角色执行睡觉动作
    this->player->toSleep();
   

//    注册触摸对象
    auto lis=EventListenerTouchOneByOne::create();
//    注册触摸开始事件
    lis->onTouchBegan=CC_CALLBACK_2(GameScene::onTouchBegan,this);
//    注册滑动事件
    lis->onTouchEnded=CC_CALLBACK_2(GameScene::onTouchEnded,this);
//    注册抬起事件
    lis->onTouchMoved=CC_CALLBACK_2(GameScene::onTouchMoved,this);
//    分发事件
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(lis,this);
    
//    开启精神状态计时器
    schedule(schedule_selector(GameScene::spiritTimer),5);
    //    开启饥饿状态计时器
    schedule(schedule_selector(GameScene::hungerTimer),6);
    //    开启开心值状态计时器
    schedule(schedule_selector(GameScene::happyTimer), 8);

//    初始化游戏状态，记录上述3中类型的值
    this->initStatus();
    return true;
}


void GameScene::initUI(){
    
//    创建菜单
    auto menu=Menu::create();
//    设置菜单坐标
    menu->setPosition(Point::ZERO);
//    按钮正常的图片资源
    string picStr[4]={"gg4.png","gg1.png","gg3.png","gg2.png"};
//    按钮被按下的图片资源
    string picAct[4]={"gg4s.png","gg1s.png","gg3s.png","gg2s.png"};
//    按钮的标题
    string btnLabel[4]={"返回","道具","食物","商店"};
    
//    开始创建菜单
    for(int i=0;i<=3;i++){
//       创建label对象用来显示菜单标题
        auto label=LabelTTF::create(btnLabel[i],"Arial", 14);
//        设置label对象的锚点
        label->setAnchorPoint(Point(0.5,0.5));
//        设置label对象的坐标
        label->setPosition(Vec2(40+this->visibleSize.width/4*i,18));
//        把Label对象添加到渲染
        this->addChild(label);
//        创建图形菜单按钮，并绑定回调函数
        auto btn=MenuItemImage::create(picStr[i],picAct[i],CC_CALLBACK_1(GameScene::selectMenuByIndex,this));
//        设置按钮的坐标
        btn->setPosition(Vec2(40+this->visibleSize.width/4*i,50));
//        设置按钮的标记，用于处理交互的时候区分不同的功能
        btn->setTag(i);
//        设置按钮c缩放
        btn->setScale(0.4);
//        加入到渲染
        menu->addChild(btn);
    }
 
    this->addChild(menu);
}


void GameScene::selectMenuByIndex(Ref*pSender){
//    将ref类型强制转换为node类型，并h获取标记
    int i=((Node*)pSender)->getTag();
    switch (i) {
        case 3:
//            打开商城
            this->gotoShop();
            break;
        case 2:
//            投喂食物
            this->gotoEat();
            break;
        case 1:
//            玩耍
            this->gotoPlay();
            break;
         case 0:
//            返回主界面
            this->goBack();
            break;
        default:
            break;
    }

}


void GameScene::gotoShop(){
//创建商店面板对象，并添加渲染
    auto shoppanel=ShopPanel::create();
    this->addChild(shoppanel);
}
void GameScene::gotoPlay(){
//玩耍，判断是否处于玩耍状态
    if(this->_isToPlay){
//        这里是创建承载玩具的面板背景
    this->panelLayer2=Sprite::create("panel.png");
    this->panelLayer2->setPosition(Point(this->visibleSize.width/2,100));
    this->panelLayer2->setScale(0.6);
    this->addChild(this->panelLayer2);
    this->_isToPlay=false;
    
//_playThing为玩具列表，表示玩具的类型
    _playThing[0]=Sprite::create("ball.png");
    _playThing[0]->setPosition(Vec2(80,105));
    _playThing[0]->setScale(0.3);
    this->addChild(_playThing[0]);

    _playThing[1]=Sprite::create("kkld.png");
    _playThing[1]->setPosition(Vec2(140,100));
    _playThing[1]->setScale(0.35);
    this->addChild(_playThing[1]);
    
    _playThing[2]=Sprite::create("pol.png");
    _playThing[2]->setPosition(Vec2(200,100));
    _playThing[2]->setScale(0.4);
    this->addChild(_playThing[2]);
    }else{
        //设置_isToPlay flag 并移除面板和玩具
        this->_isToPlay=true;
        this->panelLayer2->removeFromParent();
        for(int i=0;i<=2;i++){
            //剔除玩家选择的玩具，其他的一并移除
            if(i!=this->_selectIndexPlay){
            this->_playThing[i]->removeFromParent();
            }
        }
    }
//    this->_selectIndexPlay=-1;
}

void GameScene::gotoEat(){
    //判断现在是否在吃的状态
    if(this->_isToEat){
//        这里是场景食物种类的背景图片
        this->panelLayer=Sprite::create("panel.png");
        this->panelLayer->setPosition(Point(this->visibleSize.width/2,100));
        this->panelLayer->setScale(0.6);
        this->addChild(this->panelLayer);
        auto shopmanager=ShopManager::getInstance();
//        食物的集合，该集合的数据通过shopmamanger中得来，通过玩家购买的商品类型生成相对应的食物
        Vector<ItemInfo*> _iteminfos=shopmanager->getAllItemInfo();
//        记录食物的个数
        int offset=0;
//        遍历容器内的所有对象
        for(auto it=_iteminfos.begin();it!=_iteminfos.end();it++){
        
//            通过文件名创建sprite即食物
            auto fooditem=Sprite::create((*it)->getFileName());
            fooditem->setPosition(Vec2(100+40*offset,100));
            fooditem->setScale(0.3);
            this->addChild(fooditem);
            fooditem->setTag(offset);
            this->_foodList.pushBack(fooditem);
            values[offset]=(*it)->getEffect();
            offset++;
        }
//        记录食物个数
        this->_foodCount=offset;
        this->_isToEat=false;
    }else{
//        移除食物选择面板的所有元素
        this->toggleEatBtn();
        this->_isToEat=true;
    }
}
//开始触摸事件
bool GameScene::onTouchBegan(Touch*t,Event*e){
//    通过游戏角色生成的包围盒是否包括玩家的触摸点来确定玩家是否触摸角色
//    且角色不处于任何饥饿等状态的时候，响应玩家触摸，并播放正常时候下的动画
    if(this->player->getBoundingBox().containsPoint(t->getLocation())&&this->_isNothing&&!this->_isShowHung&&!this->_isShowUnhappy){
//        生成触摸效果，并添加到场景中
        auto tf=TouchEffect::create(0, t->getLocation());
        this->addChild(tf);
//    如果角色在睡觉的时候，触摸会让角色醒来，并播放正常状态下的动画
        if(this->_isToSleep){
            
            this->player->toNoraml();
//            设置睡觉的标记位，通过b这个标记位，可以确定角色的精神状态当下是否为增长或者减少
            this->_isToSleep=false;
        }
    }
    
//    检查玩家是否选择食物，和选择了那种食物
    if((int)(this->_foodList.size())>0){
        int currentIndex=-1;
//    遍历食物集合容器下的所有对象
        for(auto item =this->_foodList.begin();item!=this->_foodList.end();item++){
        
            currentIndex++;
//        通过食物的包围盒检查玩家的触摸点是否被包括在内，如果被包括，则判断该食物被玩家选择
            if((*item)->getBoundingBox().containsPoint(t->getLocation())){
            
//                记录现在处于持有状态
                this->_isHold=true;
//                记录被选择的的食物对象
                this->_targetFood=(*item);
//                缩放食物
                this->_targetFood->setScale(0.6);
//                把改食物从食物列表中移除
                this->_foodList.eraseObject(*item);
//                从manger中的q容器中把食物移除
                this->cleanTheFoodList(currentIndex);
//                记录被选择的食物在容器中的index
                this->selectindex=currentIndex;
                break;
            }
        }
    }
    
//    是否玩耍，同上
    if(!this->_isToPlay){
        
        for(int i=0;i<=2;i++){
            
            if(this->_playThing[i]->getBoundingBox().containsPoint(t->getLocation())){
            
                this->_targetPlayThing=this->_playThing[i];
                this->_targetPlayThing->setScale(0.6);
                this->_selectIndexPlay=i;
                this->gotoPlay();
                this->_isSelectPlay=true;
                
                break;
            }
        }
    }
    return true;
}
void GameScene::onTouchMoved(Touch*t,Event*e){
    
    if(this->_targetFood!=NULL){
//    玩家可以拖动食物
    if(this->_isHold){
        
        this->_targetFood->setPosition(t->getLocation());
    }
    }
//玩家可以拖动玩具
    if(this->_targetPlayThing!=NULL){
    if(this->_isSelectPlay){
    
        this->_targetPlayThing->setPosition(t->getLocation());
    }
    }
}
void GameScene::onTouchEnded(Touch*t,Event*e){
    
//    如果手指抬起的位置在角色的包围盒中，那么判断该食物或者玩具被角色拥有，执行相应的玩耍或者吃东西的动画，并
//    创建TipPanel对象，提示玩家现在进行什么操作，并造成什么后果
    if(this->player->getBoundingBox().containsPoint(t->getLocation())&&this->_isHold){
        
        this->_isHold=false;
//        移除食物
        this->_targetFood->removeFromParent();
//        增加相应的Progressbar的值
        this->k2->toadd(30);
//        播放吃的动画
        this->player->toEat();
//        显示提示
        auto tip=TipPanel::create(1,this->values[this->selectindex],Vec2(this->visibleSize.width/2,this->visibleSize.height/2+150));
        this->addChild(tip);
    }else if(this->_isHold){
//        移除食物
        this->_targetFood->removeFromParent();
        this->_isHold=false;
    }
    
    if(this->_isSelectPlay&&this->player->getBoundingBox().containsPoint(t->getLocation())){
//        移除玩具
        this->_targetPlayThing->removeFromParent();
        this->_isSelectPlay=false;
     
        switch (this->_selectIndexPlay) {
            case 0:{
                //                播放玩耍动画
                this->player->toPlay();
                //                并增加相应Progressbar的值
                this->k3->toadd(30);
                //               显示提示面板
                auto tip=TipPanel::create(0,10,Vec2(this->visibleSize.width/2,this->visibleSize.height/2+150));
                this->addChild(tip);
                
            }
                break;
            case 1:{
//                播放玩耍动画
                this->player->toPlay();
//                并增加相应Progressbar的值
                this->k3->toadd(30);
//                显示提示面板
                auto tip=TipPanel::create(0,20,Vec2(this->visibleSize.width/2,this->visibleSize.height/2+150));
                this->addChild(tip);
            }
                break;
            case 2:{
//                播放睡眠动画
                this->player->toSleep();
                this->_isToSleep=true;
                
            }
                break;
            default:
                break;
        }
        
    }else if(this->_isSelectPlay){
//        移除玩具
        this->_targetPlayThing->removeFromParent();
        this->_isSelectPlay=false;
    }
//    初始化数据
    this->_isNothing=true;
    this->selectindex=0;
}

void GameScene::goBack(){
//    返回主界面
    this->remenber();
    Director::getInstance()->replaceScene(HelloWorld::createScene());
}

void GameScene::selectPlayThing(Ref*pSender){
 
    this->panelLayer->removeFromParent();
}

void GameScene::cleanTheFoodList(int index){
//t移除对应index的食物对象
    this->_foodList.clear();
    auto shopmanager=ShopManager::getInstance();
    shopmanager->toDeleteItemByIndex(index);
//    遍历食物数量，判断哪一个被选中
    for(int i=this->_foodCount;i>=0;i--){
        
//        除了被选中的其他的一并移除
        if(i!=index){
        
            this->removeChildByTag(i);
        }
    }
    this->_isToEat=true;
//    移除食物面板
    this->panelLayer->removeFromParent();
}

void GameScene::spiritTimer(float dt){
 
    //精神状态定时器
    if(this->_isToSleep){
        
        this->k1->toadd(5);
        
    }else{
        
        this->k1->toless();
    }
//    如果当前值小于0，播放睡眠不足动画
    if(this->k1->getValue()<=0.0f&&!this->_isShowTire){
        
        this->_isShowTire=true;
        this->player->unsleepEffect();
        
    }else{
        
        this->_isShowTire=false;
    }
}
void GameScene::hungerTimer(float dt){

//    饥饿状态定时器
    if(this->k2->getValue()<=0&&!this->_isShowHung){
        //饥饿了//播放饥饿动画
        this->_isShowHung=true;
        this->player->hungerEffect();
        this->_isToSleep=!this->_isToSleep;
    }else{
        
        this->k2->toless();
        this->_isShowHung=false;
    }
}

void GameScene::happyTimer(float dt){

//    开心值状态定时器
   
//    如果当前状态小于0,播放不高兴的动画
    if(this->k3->getValue()<=0.0f&&!this->_isShowUnhappy){
        this->_isShowUnhappy=true;
        this->player->unhappyEffec();
        this->_isToSleep=!this->_isToSleep;
    }else{
         this->k3->toless();
         this->_isShowUnhappy=false;
    }
}

void GameScene::toggleEatBtn(){
//    切换投喂按钮
    for(int i=this->_foodCount;i>=0;i--){

        this->removeChildByTag(i);
    }
    this->panelLayer->removeFromParent();
}



void GameScene::remenber(){

    //获取userdefault对象
    auto def=UserDefault::getInstance();
    //记录精神状态
    def->setFloatForKey("spirit",this->k1->getValue());
    //记录饥饿值
    def->setFloatForKey("hunger",this->k2->getValue());
    //记录开心值
    def->setFloatForKey("happy", this->k3->getValue());
}


void GameScene::initStatus(){
    
    //获取userdefault对象
    auto def=UserDefault::getInstance();
    //获取存储的精神状态值
    float v1=def->getFloatForKey("spirit", 100.0f);
     //获取存储的饥饿状态值
    float v2=def->getFloatForKey("hunger",100.0f);
      //获取存储的开心状态值
    float v3=def->getFloatForKey("happy",100.0f);
    //把上述值设置给progressbar
    this->k1->setValue(v1);
    this->k2->setValue(v2);
    this->k3->setValue(v3);
}
